﻿using Emgu.CV;
using Emgu.CV.Structure;
using QRCodeNet.DAL;
using QRCodeNet.Scaffold;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ZXing;
using ZXing.Common;
using ZXing.OneD;

namespace QRCodeNet
{
	public partial class CompartionDlg : Form
	{
		MindVisionCamera camera;
		private delegate void AddStringToListBoxHandler(ListBox lb, string s);
		private AddStringToListBoxHandler AddStringToListBox;
		private QRCodeContext dal;
		public CompartionDlg()
		{
			InitializeComponent();
			try
			{
				camera = new MindVisionCamera(0);
				camera.OnReiceivingImage += Camera_OnReiceivingImage;
			}
			catch (Exception e)
			{
				Console.WriteLine(e.Message);
			}
			AddStringToListBox = new AddStringToListBoxHandler(AddItem);
			dal = new QRCodeContext();
		}

		private void Camera_OnReiceivingImage(object sender, ReceivingArgs e)
		{
			Mat m = new Mat(e.size, Emgu.CV.CvEnum.DepthType.Cv8U, e.channels, e.FrameBuffer, e.size.Width * e.channels);
			Console.WriteLine($"Received: {e.size.Height}*{e.size.Width}*{e.channels}.");
			ReconizeQRCode(m);
		}
		private void AddItem(ListBox lb, string item)
		{
			lb.Items.Add(item);
			if (lb.SelectedIndex == lb.Items.Count - 2 || lb.SelectedIndex < 0)
			{
				lb.SelectedIndex = lb.Items.Count - 1;
			}
		}
		public void ReconizeQRCode(Mat m)
		{
			// create a barcode reader instance
			IMultipleBarcodeReader reader = new BarcodeReader();
			var temp = reader.DecodeMultiple(m.Bitmap);

			if (temp != null)
			{
				List<Result> CurrentResults = temp.ToList();
				// do something with the result
				Console.WriteLine($"找到{CurrentResults.Count}个结果：");
				lsResult.Invoke(AddStringToListBox, new object[] { lsResult, $"找到{CurrentResults.Count}个结果：" });
				foreach (var item in CurrentResults)
				{
					dal.QRCodes.Add(new Models.QRCode()
					{
						ID = Guid.NewGuid(),
						Content = item.Text,
						Timestamp = DateTime.Now
					});
					List<string> allContent = dal.QRCodes.Select(x => x.Content).ToList();
					bool isRedundant = allContent.GetRange(Math.Max(0, allContent.Count - Config.config.HistoryNum), Math.Min(allContent.Count, Config.config.HistoryNum))
												 .Count(x => x == item.Text) > 1;
					Console.WriteLine($"{(isRedundant ? "重复：" : "")} {item.Text}");
					lsResult.Invoke(AddStringToListBox, new object[] { lsResult, $"{(isRedundant ? "重复：" : "")} {item.Text}" });
				}
				DrawResult(m, CurrentResults);
				dal.SaveChanges();
			}
			imageBox1.Invoke(new Action<Mat>(delegate (Mat img) { imageBox1.Image = img; }), new object[] { m });
		}

		private void DrawResult(IInputOutputArray input, List<Result> CurrentResults)
		{
			Random rng = new Random();
			foreach (var item in CurrentResults)
			{
				MCvScalar color = new MCvScalar(rng.Next(0, 255), rng.Next(0, 255), rng.Next(0, 255));
				foreach (var pt in item.ResultPoints)
				{
					CvInvoke.Circle(input, new Point((int)pt.X, (int)pt.Y), 20, color, -1);
				}
			}
		}

		private void BtnStart_Click(object sender, EventArgs e)
		{
			int x = dal.QRCodes.Count();
			lsResult.Invoke(AddStringToListBox, new object[] { lsResult, $"从数据库中读取{x}个记录" });
			if (camera != null)
				camera.Play();
		}
		private void ProductDlg_FormClosed(object sender, FormClosedEventArgs e)
		{
			Dispose();
		}

		private void btnStop_Click(object sender, EventArgs e)
		{
			if (camera != null)
				camera.Stop();
		}
	}
}
